﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using Microsoft.Practices.EnterpriseLibrary.Common.Utility;

namespace Microsoft.Office.PowerPoint.STAMP.Core
{
    /// <summary>
    /// Class that holds the caption information from the editor and imported file
    /// </summary>
    public class CaptionGridRow : INotifyPropertyChanged
    {
        private string _captionText;
        private TimeSpan? _endTime;
        private TimeSpan _startTime;

        private CaptionStyle _captionStyle;
        internal CaptionStyle CaptionStyle
        {
            get { return _captionStyle; }
            set
            {
                if (_captionStyle != value)
                {
                    IsDirtyCaptionStyle = true;
                    _captionStyle = value;
                    OnPropertyChanged("CaptionStyle");
                }
            }
        }

        internal string Id { get; set; }
        internal string MediaShapeName { get; set; }

        internal bool IsNew { get; set; }

        internal bool IsDirtyCaptionStyle { get; set; }
        internal bool IsDirtyCaptionText { get; set; }
        internal bool IsDirtyStartTime { get; set; }
        internal bool IsDirtyEndTime { get; set; }

        internal bool IsDirty
        {
            get { return IsDirtyCaptionText || IsDirtyStartTime || IsDirtyEndTime || IsDirtyCaptionStyle; }
        }

        /// <summary>
        /// Gets or sets caption text associated with closed caption.
        /// </summary>
        public string CaptionText
        {
            get { return _captionText; }
            set
            {
                if (_captionText != value)
                {
                    IsDirtyCaptionText = true;
                    _captionText = value;
                    OnPropertyChanged("CaptionText");
                }
            }
        }

        /// <summary>
        /// Gets or sets start time associated with closed caption.
        /// </summary>
        public TimeSpan StartTime
        {
            get { return _startTime; }
            set
            {
                if (_startTime == value) 
                    return;
                
                IsDirtyStartTime = true;
                _startTime = value;
                OnPropertyChanged("StartTime");
            }
        }

        /// <summary>
        /// Gets or sets end time associated with closed caption.
        /// </summary>
        public TimeSpan? EndTime
        {
            get { return _endTime; }
            set
            {
                if (_endTime == value)
                    return;

                IsDirtyEndTime = true;
                _endTime = value;
                OnPropertyChanged("EndTime");
            }
        }

        /// <summary>
        /// PropertyChanged event for INotifyPropertyChanged implementation.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises the PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The name of property that has a new value.</param>
        private void OnPropertyChanged(string propertyName)
        {
            ConfirmPropertyName(propertyName);

            var handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Debugging facility that ensures the property does exist on the class.
        /// </summary>
        /// <param name="propertyName"></param>
        [Conditional("Debug")]
        private void ConfirmPropertyName(string propertyName)
        {
            Debug.Assert(GetType().GetProperty(propertyName) != null, "Property " + propertyName + " is not a valid name.");
        }
    }

    /// <summary>
    /// ClosedCaptionsList contain a list of Closed Captions
    /// </summary>
    public class ClosedCaptionsSortableBindingList
    {
        /// <summary>
        /// Gets the caption grid rows contained by the collection.
        /// </summary>
        public SortableBindingList<CaptionGridRow> ClosedCaptions { get; private set; }

        /// <summary>
        /// Loads a new empty collection.
        /// </summary>
        public static ClosedCaptionsSortableBindingList Empty
        {
            get { return new ClosedCaptionsSortableBindingList { ClosedCaptions = new SortableBindingList<CaptionGridRow>() }; }

        }

        /// <summary>
        /// Orders the items by the start time.
        /// </summary>
        public void OrderByStartTime()
        {
            ClosedCaptions = new SortableBindingList<CaptionGridRow>(ClosedCaptions.OrderBy(gridRowItem => gridRowItem.StartTime));
        }

        /// <summary>
        /// Updates the name of the media shape.
        /// </summary>
        /// <param name="mediaShape">The media shape.</param>
        public void UpdateMediaShapeName(StampMediaShape mediaShape)
        {
            ClosedCaptions.ForEach(x => { x.MediaShapeName = mediaShape.MediaName; });
        }
    }

    /// <summary>
    /// ClosedCaptionsList contain a list of Closed Captions
    /// </summary>
    public class CaptionsGridRowList
    {
        /// <summary>
        /// Gets or sets the closed captions.
        /// </summary>
        /// <value>
        /// The closed captions.
        /// </value>
        public List<CaptionGridRow> ClosedCaptions { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="CaptionsGridRowList"/> class.
        /// </summary>
        public CaptionsGridRowList()
        {
            ClosedCaptions = new List<CaptionGridRow>();
        }

        /// <summary>
        /// Marks each element in the collection as new.
        /// </summary>
        public void MarkAsNew()
        {
            ClosedCaptions.ForEach(a => a.IsNew = true);
        }

        /// <summary>
        /// Updates the name of the media shape.
        /// </summary>
        /// <param name="mediaShape">The media shape.</param>
        public void UpdateMediaShapeName(StampMediaShape mediaShape)
        {
            ClosedCaptions.ForEach(x => { x.MediaShapeName = mediaShape.MediaName; });
        }
    }
}